﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DynaPrecision.LinearSystem
{
	/// <summary>
	/// A band array, based on a System.Collections.Generic.List
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class BandArray<T> : IInitializableBandArray<T>
	{
		private List<T> storage;
		/// <summary>
		/// 
		/// </summary>
		public BandArray()
		{
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="length"></param>
		/// <param name="bandHalfWidth"></param>
		public BandArray(int length, int bandHalfWidth)
		{
			Initiate(length, bandHalfWidth);
		}
		#region IBandArray<T> Members

		public int HalfBandWidth
		{
			get;
			private set;
		}
		public int Length { get; private set; }
		private int _singleStorageSectionSize { get { return HalfBandWidth * 2 + 1; } }
		private int _translatePosition(int i, int j)
		{
			if (Math.Abs(i - j) > HalfBandWidth)
			{
				return -1;
			}
			else
			{
				return i * _singleStorageSectionSize + HalfBandWidth + i - j;
			}
		}
		#endregion

		#region IMultiDimensionalArray<T> Members

		public T this[params int[] index]
		{
			get
			{
				if (Math.Abs(index[0] - index[1]) > HalfBandWidth) return (dynamic)0;
				else return storage[index[0] * _singleStorageSectionSize + HalfBandWidth + index[0] - index[1]];
			}
			set
			{
				if (Math.Abs(index[0] - index[1]) > HalfBandWidth) return;
				else storage[index[0] * _singleStorageSectionSize + HalfBandWidth + index[0] - index[1]] = value;
			}
		}

		public int GetLength(int DimensinNumber)
		{
			if (DimensinNumber == 1 || DimensinNumber == 0) return Length;
			else return 0;
		}

		public int Dimension
		{
			get { return 2; }
		}

		#endregion

		#region IInitializableBandArray<T> Members

		public void Initiate(int length, int halfBandWidth)
		{
			this.Length = length;
			this.HalfBandWidth = halfBandWidth;
			this.storage = new List<T>(ListGenerator.ConstantValueList(default(T)   , this.Length * (this._singleStorageSectionSize * 2 + 1)));
		}

		#endregion
	}
}
